package com.engine.salary.entity.datacollection.bo;

import cn.hutool.core.util.NumberUtil;
import com.engine.core.impl.Service;
import com.engine.salary.constant.SalaryDefaultTenantConstant;
import com.engine.salary.entity.datacollection.DataCollectionEmployee;
import com.engine.salary.entity.datacollection.param.VariableArchiveImportHandleParam;
import com.engine.salary.entity.datacollection.po.VariableArchiveItemPO;
import com.engine.salary.entity.datacollection.po.VariableArchivePO;
import com.engine.salary.entity.datacollection.po.VariableItemPO;
import com.engine.salary.entity.taxagent.po.TaxAgentPO;
import com.engine.salary.enums.UserStatusEnum;
import com.engine.salary.enums.salaryarchive.SalaryArchiveFieldTypeEnum;
import com.engine.salary.util.SalaryI18nUtil;
import com.engine.salary.util.db.IdGenerator;
import com.google.common.base.Joiner;
import com.google.common.collect.Lists;
import com.google.common.collect.Maps;
import org.apache.commons.collections4.CollectionUtils;
import org.apache.commons.lang3.StringUtils;
import org.apache.commons.lang3.math.NumberUtils;
import weaver.general.Util;
import weaver.hrm.User;

import java.util.*;
import java.util.stream.Collectors;

/**
 * @Description: 浮动薪资档案-excel
 * @Author: xzy
 * @Date: 2024-08-08 10:51
 */
public class VariableArchiveExcelBO extends Service {

    public static String userNameI18n;
    public static String departmentI18n;
    public static String jobNumI18n;
    public static String hrStatusI18n;
    public static String repeatMsg;
    public static String taxAgentI18n;
    public static String taxAgentRangeMsg;
    public static String empRepeatMsg;

    public static String notEmptyI18n;

    public static String incomeCategoryI18n;
    public static String salarySobI18n;
    public static String effectiveTimeI18n;
    public static String payStartDateI18n;
    public static String payEndDateI18n;
    public static String adjustReasonI18n;
    public static String listTypeErrMsg;
    public static String taxAgentNoExist;
    public static String incomeCategoryNoExist;
    public static String currSalarySobI18n;
    public static String noExist;
    public static String effectiveTimeErr;
    public static String adjustReasonNoExist;
    public static String dateErr;
    public static String payStartUnableAfterEnd;

    public static String salaryItemNoBeforeCurrentEffectiveTime;
    public static String salaryItemAdjustNoSame;
    public static String salaryItemAdjustNoSameIneffective;

    public static String salaryArchiveErr;
    public static String numberErr;

    /**
     * 初始化i18n
     */
    public static void initI18n() {
        userNameI18n = SalaryI18nUtil.getI18nLabel(85429, "姓名");
        departmentI18n = SalaryI18nUtil.getI18nLabel(86185, "部门");
        jobNumI18n = SalaryI18nUtil.getI18nLabel(86317, "工号");
        hrStatusI18n = SalaryI18nUtil.getI18nLabel(109332, "人事状态");
        repeatMsg = "[" + Joiner.on(",").join(new List[]{Arrays.asList(userNameI18n, departmentI18n, jobNumI18n, hrStatusI18n)}) + "]";
        taxAgentI18n = SalaryI18nUtil.getI18nLabel(86184, "个税扣缴义务人");
        taxAgentRangeMsg = SalaryI18nUtil.getI18nLabel(132633, "该员工不在该个税扣缴义务人的人员范围中") + "," + SalaryI18nUtil.getI18nLabel(127308, "请检查") + repeatMsg;
        empRepeatMsg = SalaryI18nUtil.getI18nLabel(121899, "员工信息重复，请检查") + repeatMsg;

        notEmptyI18n = SalaryI18nUtil.getI18nLabel(100577, "不能为空");

        incomeCategoryI18n = SalaryI18nUtil.getI18nLabel(121908, "收入所得项目");
        salarySobI18n = SalaryI18nUtil.getI18nLabel(87889, "薪资账套");
        effectiveTimeI18n = SalaryI18nUtil.getI18nLabel(85904, "生效日期");
        payStartDateI18n = SalaryI18nUtil.getI18nLabel(109527, "起始发薪日期");
        payEndDateI18n = SalaryI18nUtil.getI18nLabel(109329, "最后发薪日期");
        adjustReasonI18n = SalaryI18nUtil.getI18nLabel(85431, "调整原因");

        listTypeErrMsg = SalaryI18nUtil.getI18nLabel(115527, "该条数据不符合当前列表导入要求或其他列表存在该档案，不可导入");

        taxAgentNoExist = SalaryI18nUtil.getI18nLabel(100545, "个税扣缴义务人不存在");
        incomeCategoryNoExist = SalaryI18nUtil.getI18nLabel(121923, "收入所得项目不存在");

        currSalarySobI18n = SalaryI18nUtil.getI18nLabel(127213, "该收入所得项目");
        noExist = SalaryI18nUtil.getI18nLabel(127236, "不存在");

        effectiveTimeErr = SalaryI18nUtil.getI18nLabel(102497, "生效日期错误或格式不正确，正确格式示例为'2022-01-01'、'2022/1/1'");
        adjustReasonNoExist = SalaryI18nUtil.getI18nLabel(100591, "调整原因不存在");

        dateErr = SalaryI18nUtil.getI18nLabel(109819, "日期错误或格式不正确，正确格式示例为'2022-01-01'、'2022/1/1'");

        payStartUnableAfterEnd = SalaryI18nUtil.getI18nLabel(109214, "起始发薪日期不可晚于最后发薪日");

        salaryItemNoBeforeCurrentEffectiveTime = SalaryI18nUtil.getI18nLabel(100429, "生效日期不可早于当前已生效的调整日期");
        salaryItemAdjustNoSame = SalaryI18nUtil.getI18nLabel(100432, "调整前后不可相同");
        salaryItemAdjustNoSameIneffective = SalaryI18nUtil.getI18nLabel(100434, "与未生效的调整后不可相同");

        salaryArchiveErr = SalaryI18nUtil.getI18nLabel(101723, "该员工的薪资档案记录有误，请检查");
        numberErr = SalaryI18nUtil.getI18nLabel(100581, "请输入数字");

    }


    /**
     * 校验单行数据
     *
     * @param map
     * @param headers
     * @param excelComments
     * @param errorCount
     * @param importHandleParam
     * @return
     */
    public static boolean singleRowCheck(List<String> allTodoVariableArchives,
                                         Map<String, Object> map,
                                         List<String> headers,
                                         List<Map<String, String>> excelComments,
                                         int errorCount,
                                         VariableArchiveImportHandleParam importHandleParam,
                                         User user) {

        boolean isError = false;
        String rowindex = "第" + map.get("index") + "行";
        // 1.姓名
        String userName = Optional.ofNullable(map.get(userNameI18n)).orElse("").toString();
        String deparmentName = Optional.ofNullable(map.get(departmentI18n)).orElse("").toString();
        String mobileName = Optional.ofNullable(map.get("手机号")).orElse("").toString();
        String workcode = Optional.ofNullable(map.get("工号")).orElse("").toString();
        String idNo = Optional.ofNullable(map.get("证件号码")).orElse("").toString();

        String validType = importHandleParam.getEmpValidType();
        List<DataCollectionEmployee> emps = new ArrayList<>();
        if ("0".equals(validType)) {
            //“0”代表姓名+部门+手机号的匹配原则，“1”代表工号为唯一匹配原则
            emps = importHandleParam.getEmployees().stream().filter(e ->
                    (StringUtils.isBlank(userName) || Objects.equals(e.getUsername(), userName))
                            && (StringUtils.isBlank(deparmentName) || Objects.equals(e.getDepartmentName(), deparmentName))
                            && (StringUtils.isBlank(mobileName) || Objects.equals(e.getMobile(), mobileName))).collect(Collectors.toList());
        } else if ("1".equals(validType)) {
            emps = importHandleParam.getEmployees().stream().filter(e -> (StringUtils.isBlank(workcode) || Objects.equals(e.getWorkcode(), workcode)))
                    .collect(Collectors.toList());
        }
        else if ("2".equals(validType)) {
            emps = importHandleParam.getEmployees().stream().filter(e -> (StringUtils.isBlank(idNo) || Objects.equals(e.getIdNo(), idNo)))
                    .collect(Collectors.toList());
        }

        List<Long> employeeSameIds = new ArrayList<>();
        if (CollectionUtils.isNotEmpty(emps) && emps.size() > 1) {
            employeeSameIds = emps.stream().filter(e -> UserStatusEnum.getNormalStatus().contains(e.getStatus())).map(DataCollectionEmployee::getEmployeeId).collect(Collectors.toList());
        }
        if (CollectionUtils.isNotEmpty(emps) && emps.size() == 1) {
            employeeSameIds = emps.stream().map(DataCollectionEmployee::getEmployeeId).collect(Collectors.toList());
        }
        Long employeeId = CollectionUtils.isNotEmpty(employeeSameIds) && employeeSameIds.size() == 1 && employeeSameIds.get(0) > 0 ? employeeSameIds.get(0) : null;

        if (employeeId == null) {
            Map<String, String> errorMessageMap = Maps.newHashMap();
            errorMessageMap.put("message", rowindex + "查找人员失败，请确定姓名、部门、手机号正确且唯一");
            excelComments.add(errorMessageMap);
            isError = true;
            return isError;
        }

        // 个税扣缴义务人
        String taxAgentCellVal = Optional.ofNullable(map.get(taxAgentI18n)).orElse("").toString();
        map.put("taxAgent", taxAgentCellVal);
        Optional<TaxAgentPO> optionalTaxAgent = importHandleParam.getTaxAgentList().stream().filter(m -> m.getName().equals(taxAgentCellVal)).findFirst();
        if (!optionalTaxAgent.isPresent()) {
            Map<String, String> errorMessageMap = Maps.newHashMap();
            errorMessageMap.put("message", rowindex + "个税扣缴义务人不存在，或不在权限范围内");
            excelComments.add(errorMessageMap);
            isError = true;
            return isError;
        }
        Long taxAgentId = optionalTaxAgent.get().getId();
        map.put("taxAgentId", taxAgentId);

        // 用于初始化导入数据校验
        map.put("employeeId", employeeId);
        String repeatKey = optionalTaxAgent.get().getId() + "-" + employeeId.toString();
        if (allTodoVariableArchives.contains(repeatKey)) {
            Map<String, String> errorMessageMap = Maps.newHashMap();
            errorMessageMap.put("message", rowindex + "存在重复数据");
            excelComments.add(errorMessageMap);
            isError = true;
            return isError;
        } else {
            allTodoVariableArchives.add(repeatKey);
        }

        // 构建薪资档案
        VariableArchivePO finalVariableArchive = buildVariableArchive(employeeId, taxAgentId, importHandleParam);
        map.put("variableArchiveId", finalVariableArchive.getId());
        List<Long> needDelArchiveItemIds = new ArrayList<>();
        for (int j = 0; j < headers.size(); j++) {
            String header = headers.get(j);
            Object key = header;
            if (key == null) {
                continue;
            }
            String cellVal = Optional.ofNullable(map.get(key.toString())).orElse("").toString();


            boolean isNotEmpty = StringUtils.isNotEmpty(cellVal);
            // 1.姓名列处理
            if (isNotEmpty && userNameI18n.equals(key.toString())) {
                if (CollectionUtils.isEmpty(employeeSameIds) || employeeSameIds.size() > 1) {
                    Map<String, String> errorMessageMap = Maps.newHashMap();
                    errorMessageMap.put("message", rowindex + header + empRepeatMsg);
                    excelComments.add(errorMessageMap);
                    isError = true;
                }
            }  else {
                // 浮动薪资项目数据
                if (!isError) {
                    Optional<VariableItemPO> optionalVariableItem = importHandleParam.getVariableItems().stream().filter(e -> Util.formatMultiLang(e.getName(), String.valueOf(user.getLanguage())).equals(key)).findFirst();

                    if (optionalVariableItem.isPresent()) {
                        VariableItemPO variableItemPO = optionalVariableItem.get();
                        // 数值类型判断
                        boolean isNotNumber = variableItemPO.getDataType().equals(SalaryArchiveFieldTypeEnum.NUMBER.getValue()) && StringUtils.isNotEmpty(cellVal) && !NumberUtil.isNumber(cellVal);
                        if (isNotNumber) {
                            Map<String, String> errorMessageMap = Maps.newHashMap();
                            errorMessageMap.put("message", rowindex + key + numberErr);
                            excelComments.add(errorMessageMap);
                            isError = true;
                        }
                        Long variableItemId = variableItemPO.getId();
                        // 已生效
                        List<VariableArchiveItemPO> effectiveList = Optional.ofNullable(importHandleParam.getEffectiveItemListMap().get(finalVariableArchive.getId() + "-" + variableItemId)).orElse(Lists.newArrayList());
                        // 先删除后新增
                        needDelArchiveItemIds.addAll(effectiveList.stream().map(VariableArchiveItemPO::getId).collect(Collectors.toList()));

                        // 导入时不需要处理的项目
                        boolean isInitNull = CollectionUtils.isEmpty(effectiveList) && StringUtils.isEmpty(cellVal);
                        if (!isError && !isInitNull && StringUtils.isNotBlank(cellVal)) {
                            importHandleParam.getVariableArchiveItemSaves().add(VariableArchiveItemPO.builder()
                                    .id(IdGenerator.generate())
                                    .employeeId(finalVariableArchive.getEmployeeId())
                                    .variableArchiveId(finalVariableArchive.getId())
                                    .variableItemId(variableItemId)
                                    .itemValue(cellVal)
                                    .creator(importHandleParam.getCurrentEmployeeId())
                                    .createTime(importHandleParam.getNowTime())
                                    .updateTime(importHandleParam.getNowTime())
                                    .deleteType(NumberUtils.INTEGER_ZERO)
                                    .tenantKey(SalaryDefaultTenantConstant.DEFAULT_TENANT_KEY)
                                    .build());
                        }
                    }
                }
            }
        }

        // 如果当前校验行没问题,修改起始发薪日期和最终发薪日期等
        if (isError) {
            // 将前面添加好的数据给过滤掉
            importHandleParam.setVariableArchiveSaves(importHandleParam.getVariableArchiveSaves().stream().filter(f -> !finalVariableArchive.getId().equals(f.getId())).collect(Collectors.toList()));
            importHandleParam.setVariableArchiveItemSaves(importHandleParam.getVariableArchiveItemSaves().stream().filter(f -> !finalVariableArchive.getId().equals(f.getVariableArchiveId())).collect(Collectors.toList()));
        } else {
            importHandleParam.getVariableArchiveItemDelSalaryItemIds().addAll(needDelArchiveItemIds);
        }

        return isError;
    }


    /**
     * 构建浮动薪资档案对象
     *
     * @param employeeId
     * @param taxAgentId
     * @param importHandleParam
     * @return
     */
    public static VariableArchivePO buildVariableArchive(Long employeeId, Long taxAgentId, VariableArchiveImportHandleParam importHandleParam) {
        VariableArchivePO variableArchivePO = importHandleParam.getVariableArchivesMap().get(taxAgentId + "-" + employeeId);
        if (variableArchivePO == null) {
            // 新增浮动档案
            variableArchivePO = VariableArchivePO.builder()
                    .id(IdGenerator.generate())
                    .employeeId(employeeId)
                    .taxAgentId(taxAgentId)
                    .salaryMonth(importHandleParam.getSalaryMonthDate())
                    .createTime(importHandleParam.getNowTime())
                    .updateTime(importHandleParam.getNowTime())
                    .creator(importHandleParam.getCurrentEmployeeId())
                    .deleteType(NumberUtils.INTEGER_ZERO)
                    .tenantKey(SalaryDefaultTenantConstant.DEFAULT_TENANT_KEY)
                    .build();
            importHandleParam.getVariableArchiveSaves().add(variableArchivePO);
        }
        return variableArchivePO;
    }


    @Override
    public String toString() {
        return "SalaryArchiveExcelBO{}";
    }
}
